import htmlWord from "./html-word.js";
import saveAs from "file-saver";
import errorImg from "./error.png";
import html2canvas from "html2canvas";
// import { isArray } from "element-plus/es/utils/types.mjs";

function isArray(value) {
  return Object.prototype.toString.call(value) === '[object Array]';
}

const convertImagesToBase64 = (item, timeOut, defultImg) => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = ""; //允许图片跨域
    img.src = item.src;
    // 图片加载
    img.onload = function () {
      // 图片加载完成后进行绘制
      const canvas = document.createElement("canvas");

      const originalWidth = img.width* 5;
      const originalHeight = img.height* 5;

      // 设置画布为图片原本尺寸的5倍大小
      canvas.width = originalWidth;
      canvas.height = originalHeight;

      const ctx = canvas.getContext("2d");
      // 缩放画布到原始尺寸
      // ctx.scale(1 / 5, 1 / 5);

      // 绘制图片
      ctx.drawImage(img, 0, 0, originalWidth, originalHeight);

      // 恢复缩放状态
      // ctx.setTransform(1, 0, 0, 1, 0, 0);
      // ctx?.drawImage(img, 0, 0, item.width, item.height);
      const ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
      const dataURL = canvas.toDataURL("image/" + ext, 1.0);
      item.setAttribute("src", dataURL);
      item.style.width = `${img.width}px`;
      item.style.height = `${img.height}px`;

      canvas.remove(); //移除canvas
      clearTimeout(timer);
      resolve(dataURL);
    };

    // 图片加载失败
    img.onerror = async () => {
      clearTimeout(timer);
      await getDefaultImg();
      console.error("图片加载异常:", img.src);
      resolve("xh-htmlword: 图片加载异常");
    };

    // 超时时间处理
    const timer = setTimeout(async () => {
      await getDefaultImg();
      console.error("图片加载超时:", img.src);
      resolve("xh-htmlword: 图片加载超时");
    }, timeOut);

    // 获取默认图片
    const getDefaultImg = () => {
      return new Promise((res) => {
        const imgError = new Image();
        imgError.crossOrigin = ""; //允许图片跨域
        imgError.src = defultImg || errorImg;
        imgError.onload = () => {
          // 图片加载完成后进行绘制
          const canvas = document.createElement("canvas");
          canvas.width = item.width; //保证文档和图片宽高一致
          canvas.height = item.height;
          const ctx = canvas.getContext("2d");
          ctx?.drawImage(imgError, 0, 0, item.width, item.height);
          const ext = imgError.src
            .substring(imgError.src.lastIndexOf(".") + 1)
            .toLowerCase();
          const dataURL = canvas.toDataURL("image/" + ext, 1.0);
          item.setAttribute("src", dataURL);
          canvas.remove(); //移除canvas
          res();
        };
      });
    };
  });
};

// 根据当前html页面导出word文档
/**
 * @params
 *  dom：需要渲染的html父盒子标签 ， 类型：string 例如 id/class
 *  fileName：文件名称 类型：string
 *  callBack：导出成功回调函数
 *  timeOut:设置导出图片加载 超时时间 默认值 5000  (5s)
 *  options:配置项  类型：object 例如可传 {left:1440,right:1440} 控制页边距
 *  defultImg: 错误或者超时图片 默认图片地址 类型：string
 *  className:当前组件的class属性名标识 类型：string  可以在标签写入class样式
 *  drawCanvas:当当前页面有比较复杂的样式或组件（element-ui等） 页面中可以用样式标签将它包裹起来然后将标签 传入drawCanvas数组中 开启转换
 */

const handleExportWord = async ({
  element,
  fileName = getTime(),
  timeOut = 5000,
  callBack,
  options = {},
  defultImg,
  className,
  drawCanvas,
}) => {
  const app = element;
  const cloneApp = app.cloneNode(true);

  console.log('cloneApp')
  console.log(cloneApp)

  // // 是否开启使用html2canvas渲染dom
  if (drawCanvas && drawCanvas.length > 0 && isArray(drawCanvas)) {
    const canvasPromiseAll = [];
    drawCanvas.map((item) => {
      const domList = app.querySelectorAll(item);

      console.log('domList')
      console.log(domList)
      if (domList.length == 0)
        throw new Error(`dom不存在：“${item}” , 请检查传入的dom标签是否正确`);
      domList.forEach((v, index) => {
        canvasPromiseAll.push(
          new Promise((resolve, reject) => {
            html2canvas(v, {
              scale: 1,
              width: v.offsetWidth,
              height: v.offsetHeight,
              allowTaint: true,
              useCORS: true,
            }).then((canvas) => {
              const cloneCanvasDom = cloneApp.querySelectorAll(item)[index];
              cloneCanvasDom.innerHTML = "";
              const url = canvas.toDataURL("image/png", 1);
              const img = new Image();
              img.onload = () => {
                URL.revokeObjectURL(url);
              };
              img.src = url;
              cloneCanvasDom.appendChild(img);
              resolve(canvas);
            });
          })
        );
      });
    });
    await Promise.all(canvasPromiseAll);
  }

  const canvases = app?.getElementsByTagName("canvas");
  const cloneCanvases = cloneApp?.getElementsByTagName("canvas");
  const promises = Array.from(canvases).map((ca, index) => {
    return new Promise((res) => {
      const url = ca.toDataURL("image/png", 1);
      const img = new Image();
      img.onload = () => {
        URL.revokeObjectURL(url);
        res();
      };
      img.src = url;
      // 生成img插入clone的dom的canvas之前
      cloneCanvases[index].parentNode.insertBefore(img, cloneCanvases[index]);
    });
  });

  // 移除原来的canvas
  const cloneCanvas = cloneApp.getElementsByTagName("canvas");
  Array.from(cloneCanvas).forEach((ca) => ca.parentNode.removeChild(ca));
  Promise.all(promises).then(async () => {
    // 关键代码
    const regularImages = [...cloneApp.getElementsByTagName("img")];
    let promiseArray = [];
    regularImages.forEach((item) => {
      promiseArray.push(convertImagesToBase64(item, timeOut, defultImg));
    });
    await Promise.all(promiseArray);
    const HTML = `
  <html xmlns:o=\'urn:schemas-microsoft-com:office:office\' xmlns:w=\'urn:schemas-microsoft-com:office:word\' xmlns=\'http://www.w3.org/TR/REC-html40\'><head>
  </head>
  <body>
  ${cloneApp.outerHTML}
  </body>
  </html>`;

    const content = insertCss(HTML, className);
    console.log(content)
    console.log(content)

    const converted = htmlWord.asBlob(content, options);
    console.log(converted)
    // saveAs(converted, `${fileName}.docx`);
    callBack && callBack(converted); //执行回调
  });
};

// 将class名转换成style属性
function insertCss(content, className) {
  // 此处对分页进行转换
  content = content.replace(/break-before: page/g, `page-break-before: always`);

  if (!className) return content;
  [...getCssBlock(className)].forEach((v) => {
    if (content.includes(getCssName(v.selectorText))) {
      // 如果包含 则替换 对应成style
      let regex = new RegExp(`class="${getCssName(v.selectorText)}"`, "g");
      content = content.replace(regex, `style="${v.style.cssText}"`);
    }
  });

  return content;
}

/*
 * 获取css中当前组件的class名
 * */
function getCssName(str) {
  let matchResult = str.match(/\.(\w+)/);
  if (matchResult) {
    let extractedPart = matchResult[1];
    return extractedPart;
  } else {
    console.log("没有找到匹配的部分");
  }
}

// 获取style表中当前组件的css规则
function getCssBlock(className) {
  const cssBlock = document.styleSheets;
  const styleData = [...cssBlock].reverse().find(({ cssRules }) => {
    return [...cssRules].find((rule) => {
      return rule.selectorText.includes(className);
    });
  });
  return styleData.cssRules;
}

// 获取时间
const getTime = () => {
  const now = new Date();
  const year = now.getFullYear();
  const month = ("0" + (now.getMonth() + 1)).slice(-2);
  const day = ("0" + now.getDate()).slice(-2);

  const formattedTime = `${year}${month}${day}`;
  return formattedTime;
};

export default handleExportWord;
